/*
 *The code is written by NaLi, All rights reserved.
 */
package com.nali.dal.statement.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import org.apache.commons.lang.StringUtils;

/**
 * @author gavin Created on 2010-7-12
 */
public class DalDateUtils {
	private static final long DAY_MILLISECONDS = 1000L * 3600 * 24;
	public static final String DEFAULT_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
	private static final String[] patterns = new String[] { "yyyy-MM-dd", DEFAULT_TIME_PATTERN};
	public static final Date START_DATE = new Date(0);
	private static final long START_SECONDS = (int) (START_DATE.getTime() / 1000);
	public static final long SECOND_TIME_MILLS = 1000;
	public static final long MINUTE_TIME_MILLS = SECOND_TIME_MILLS * 60;
	public static final long HOUR_TIME_MILLS = MINUTE_TIME_MILLS * 60;
	public static final long DAY_TIME_MILLS = 24 * HOUR_TIME_MILLS;
	public static final long YEAR_TIME_MILLS = 365 * DAY_TIME_MILLS;
	public static final Calendar START_CALENDAR;
	
	public static final Date DATE_2000;
	
	static {
		Calendar cal2000 = Calendar.getInstance();
		cal2000.set(2000, 0, 1, 0, 0, 0);
		DATE_2000 = cal2000.getTime();
		
		START_CALENDAR = Calendar.getInstance();
		START_CALENDAR.setTime(START_DATE);
	}
	
	public static Date getDate(long duration) {
		long durationTimeMills =  (duration + START_SECONDS ) * 1000;
		return new Date(durationTimeMills);
	}

	/**
	 * 删除时间部分数据,精确到年月日
	 * 
	 * @param cal
	 */
	public static void truncateTime(Calendar cal) {
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
	}
	
	public static Date truncateHour(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTime();
	}
	
	public static Date truncateMonth(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.DAY_OF_MONTH, 1);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTime();
	}
	
	public static Date truncateYear(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.MONTH, 0);
		c.set(Calendar.DAY_OF_MONTH, 1);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTime();
	}
	
	public static Date truncateWeek(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.DAY_OF_WEEK, 1);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTime();
	}
	
	public static Date truncateSecond(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTime();
	}
	
	/**
	 * 精确到年月日并转为Long
	 * 
	 * @param cal
	 * @return 时间TimeInMillis
	 */
	public static long truncateTimeToLong(Calendar cal) {
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTimeInMillis();
	}

	/**
	 * 精确到年月日并转为Long
	 * 
	 * @param cal
	 * @return 时间TimeInMillis
	 */
	public static long truncateTimeToLong(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTimeInMillis();
	}

	public static Date truncateTime(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTime();
	}
	

	public static Date truncateToTimeUnit(Date startTime, long timeUnit, Date time) {
		long timeMills = time.getTime();
		long initMills = startTime.getTime();
		long duration = timeMills - initMills;
		long unitLeft = duration % timeUnit;
		long rtn = timeMills - unitLeft;
		return new Date(rtn);
	}

	public static Date parseDateTime(String toCloseTimeString) throws ParseException {
		return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(toCloseTimeString);
	}
	
	public static Date parseDateMonth(String toCloseTimeString) throws ParseException {
		return new SimpleDateFormat("yyyyMM").parse(toCloseTimeString);
	}

	public static Date parseAuto(String dateString) {
		if (StringUtils.isEmpty(dateString))
			return null;
		try {
			return org.apache.commons.lang.time.DateUtils.parseDate(dateString.trim(), patterns);
		} catch (ParseException e) {
		}
		return null;
	}
	
	public static Date convertGMTToLocale(Date gmtDate) {
		Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
		cal.setTime(gmtDate);
		cal.setTimeZone(TimeZone.getDefault());
		return cal.getTime();
	}
	
	
	public static Date parse(String dateString, String format) throws ParseException {
		return new SimpleDateFormat(format).parse(dateString);
	}
	
	public static Date parseGMTTOLocale(String dateString, String format) throws ParseException {
		Date gmtDate =  new SimpleDateFormat(format).parse(dateString);
		Date localeDate = convertGMTToLocale(gmtDate);
		return localeDate;
	}
	
	/**
	 * 得到当天的最后一秒
	 * 
	 * @param date
	 * @return
	 */
	public static Date getLastSecondOfDay(Date date) {
		if (date == null)
			return null;
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		return cal.getTime();
	}

	public static Date parseVoteDate(String toCloseTimeString) throws ParseException {
		return new SimpleDateFormat("yyyy-MM-dd HH").parse(toCloseTimeString);
	}

	/**
	 * 返回ｎ个月前的时间
	 * 
	 * @param from
	 * @param i
	 * @return
	 */
	public static Date beforeMonth(Date from, int i) {
		return org.apache.commons.lang.time.DateUtils.addMonths(from, -i);
	}

	/**
	 * 2000年1月1日,零时
	 * 
	 * @return
	 */
	public static String get2000() {
		return "Sat,01 Jan 2000 00:00:00 GMT";
	}

	/**
	 * 2000年1月1日,零时
	 * 
	 * @return
	 */
	public static Date get2000Date() {
		return DATE_2000;
	}

	/**
	 * 计算两个日期差多少天. 不分前后
	 * 
	 * @param from
	 * @param to
	 * @return 天数的绝对值
	 */
	public static int calcDaysBetween(Date from, Date to) {
		long millis = Math.abs(truncateTimeToLong(to) - truncateTimeToLong(from));
		if (millis == 0)
			return 0;
		if(millis % DAY_MILLISECONDS == 0)
			return (int) (millis / DAY_MILLISECONDS);
		return (int) (millis / DAY_MILLISECONDS) + 1;
	}

	/**
	 * 计算从2000年开始到现在的天数
	 * 
	 * @return
	 */
	public static int calcDaysFrom2000() {
		return calcDaysBetween(DATE_2000, new Date());
	}
	
	/**
	 * 计算从2000年开始到现在的天数
	 * @param which
	 * @return
	 */
	public static int calcDaysFrom2000(Date which) {
		return calcDaysBetween(DATE_2000, which);
	}

	/**
	 * 把日期增大N天
	 * @param old
	 * @param days (如果为负数,则日期变小)
	 * @return
	 */
	public static Date addDays(Date old, int days) {
		Calendar now = Calendar.getInstance();
		now.setTime(old);
		now.setTimeInMillis(now.getTimeInMillis() + days * 1000L * 24 * 3600);
		return now.getTime();
	}

	public static Date now() {
		return new Date();
	}
	
	public static Date month() {
		return truncateMonth(new Date());
	}
	
	public static Calendar getCalendar(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal;
	}
	
	public static int calcMonthBetween(Date from, Date to) {
		Calendar fromCal = getCalendar(from);
		Calendar toCal = getCalendar(to);
		int fromYear = fromCal.get(Calendar.YEAR);
		int fromMonth = fromCal.get(Calendar.MONTH);
		int toYear = toCal.get(Calendar.YEAR);
		int toMonth = toCal.get(Calendar.MONTH);
		
		return (toYear - fromYear) * 12 + toMonth - fromMonth;
	}
}
